﻿// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Castle.DynamicProxy;

namespace Microsoft.ClientModel.TestFramework;

internal class ProxyResultInterceptor : IInterceptor
{
    private readonly ClientTestBase _testBase;

    public ProxyResultInterceptor(ClientTestBase testBase)
    {
        _testBase = testBase;
    }

    public void Intercept(IInvocation invocation)
    {
        var type = invocation.Method.ReturnType;

        if (CanProxyClient(invocation))
        {
            if (IsNullResult(invocation))
                return;

            if (invocation.ReturnValue is null)
            {
                throw new InvalidOperationException("Unexpected error: Could not find original client.");
            }

            invocation.ReturnValue = _testBase.CreateProxyFromClient(type, invocation.ReturnValue, Array.Empty<IInterceptor>());
            return;
        }

        invocation.Proceed();
    }

    private static bool CanProxyClient(IInvocation invocation)
    {
        var type = invocation.Method.ReturnType;

        // System types, rest clients, extension clients are not proxied
        if (type.Namespace?.StartsWith("System.") == true || type.Name.EndsWith("RestClient") || type.Name.EndsWith("ExtensionClient"))
        {
            return false;
        }

        // Clients and subclients without "Client" suffix are proxied
        if (type.Name.EndsWith("Client") || (type.IsPublic && type.GetProperty("Pipeline") != null))
        {
            return true;
        }

        return false;
    }

    private bool IsNullResult(IInvocation invocation)
    {
        invocation.Proceed();
        return invocation.ReturnValue == null;
    }
}
